﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using KDG.FoldersSize.Scaner;
using System.Windows.Forms;
using System.IO;
using KDG.Sys;
using System.Windows.Media.Effects;
using KDG.FoldersSize;
using System.Windows.Threading;


namespace FoldersSize
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        Scaner scaner = null;
        ScanerItem root = null;
        //private bool _scaning = false;
        private static int ProgressStatusChangingStep = 100;
        private int _progressStatusChangingStep = 1;

        // ctors
        public Window1()
        {
            InitializeComponent();
            Scaning = false;
            this.Resources["HasData"] = false;
            fdControl.SetRoot(ref root);
        }

        public readonly DependencyProperty SacanigProperty = DependencyProperty.Register("Scaning", typeof(bool), typeof(Window1));

        // Determine scaning process
        public bool Scaning
        {
            get
            {
                return (bool)GetValue(SacanigProperty);
            }
            set
            {
                SetValue(SacanigProperty, value);

                this.stStatusAdvanced.Visibility = value ? Visibility.Collapsed : Visibility.Visible;

                int blurRadius = value ? 10 : 0;
                (this.stackPath.Effect as BlurEffect).Radius = blurRadius;
                (this.controlPanel.Effect as BlurEffect).Radius = blurRadius;
            }
        }




        private void PathButtonClick(object sender, System.Windows.RoutedEventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog() { SelectedPath = tbPath.Text, ShowNewFolderButton = false };

            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                tbPath.Text = fbd.SelectedPath;
        }

        private void btScanClick(object sender, System.Windows.RoutedEventArgs e)
        {
            if (!Scaning)
            {
                scaner = new Scaner();
                trFiles.Items.Clear();
                scaner = new Scaner();
                scaner.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(scaner_ProgressChanged);
                scaner.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(scaner_RunWorkerCompleted);

                Scaning = true;
                scaner.ScanAsync(tbPath.Text);
            }
        }
        private void CancelScan(object sender, System.Windows.RoutedEventArgs e)
        {
            if (scaner != null)
                scaner.CancelAsync();
        }
        private void FillTree(ScanerItem scanerItem, TreeViewItem Leaf)
        {
            scanerItem.Childs.ForEach(x =>
                {
                    TreeViewItem tvi = new TreeViewItem();
                    tvi.DataContext = new ScanerItemString(ref x);
                    Leaf.Items.Add(tvi);

                    if (x.IsDirectory)
                        FillTree(x, tvi);
                }
            );
        }

        // Scanner events handlers
        private void scaner_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            Scaning = false;
            this.Resources["HasData"] = true;


            if (e.Cancelled)
            {
                tbStatus.Text = string.Format("Scan canceled.", tbPath.Text);
                this.stStatusAdvanced.Visibility = Visibility.Collapsed;
                return;
            }

            tbStatus.Text = string.Format("Scan of [{0}] completed.", tbPath.Text);

            root = e.Result as ScanerItem;
            fdControl.SetRoot(ref root);
            
            if (root != null)
            {
                TreeViewItem tvi = new TreeViewItem();
                tvi.DataContext = new ScanerItemString(ref root);
                trFiles.Items.Add(tvi);

                //animScan.StopAnim();

                stStatusAdvanced.DataContext = new ScanerItemString(ref root);

                FillTree(root, tvi);

                scaner = null;
            }
        }
        private void scaner_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            if (_progressStatusChangingStep == 0)
            {
                animScan.StatusText = tbStatus.Text = string.Format("Scaning... [{0}]", e.UserState);
                _progressStatusChangingStep = Window1.ProgressStatusChangingStep;
                return;
            }

            _progressStatusChangingStep--;
        }

        // Save methods
        private void SaveToTxt(object sender, System.Windows.RoutedEventArgs e)
        {
            SaveFileDialog ofd = new SaveFileDialog() { DefaultExt = "*.txt", AddExtension = true, Filter = "Text files|*.txt|All files|*.*", Title = "[Save as Txt]kDg.Folders size" };
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {

                using (StreamWriter sw =
                    new StreamWriter(ofd.FileName, false, Encoding.Default))
                {
                    SaveScanerItemToTxt(sw, root);
                    sw.Close();
                }
                tbStatus.Text = string.Format("Save to [{0}] completed.", ofd.FileName);
            }
        }
        private void SaveScanerItemToTxt(StreamWriter sw, ScanerItem Item)
        {
            sw.Write((Item.IsDirectory ? "[" : "") + Item.FullName + (Item.IsDirectory ? "]" : ""));
            sw.WriteLine(string.Format(FileSizeFormatProvider.Provider, "{0}", Item.Length));
            Item.Childs.ForEach(x => SaveScanerItemToTxt(sw, x));
        }

        private void SaveToHtml(object sender, System.Windows.RoutedEventArgs e)
        {
            SaveFileDialog ofd = new SaveFileDialog() { DefaultExt = "*.html", AddExtension = true, Filter = "HTML files|*.html|All files|*.*", Title = "[Save as Html]kDg.Folders size" };
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {

                using (StreamWriter sw =
                    new StreamWriter(ofd.FileName, false, Encoding.Default))
                {
                    sw.Write("<body><table>\r\n");
                    SaveScanerItemToHtml(sw, root, 0);
                    sw.Write("</table></body>\r\n");

                    sw.Close();
                }
                tbStatus.Text = string.Format("Save to [{0}] completed.", ofd.FileName);
            }
        }
        private void SaveScanerItemToHtml(StreamWriter sw, ScanerItem Item, int Deep)
        {
            sw.Write("<tr>");

            StringBuilder sb = new StringBuilder();
            sb.Append('-', Deep);
            sw.Write(sb);

            if (Item.IsDirectory)
                sw.Write("<b>");
            sw.Write("<a href=\"{0}\">{1} ({2})</a>",
                Item.FullName,
                (Item.IsDirectory ? "[" : "") + Item.Name + (Item.IsDirectory ? "]" : ""),
                string.Format(FileSizeFormatProvider.Provider, "{0}", Item.Length));

            if (Item.IsDirectory)
                sw.Write("</b>");
            sw.Write("</tr>");
            sw.Write(sw.NewLine);

            Item.Childs.ForEach(x => SaveScanerItemToHtml(sw, x, Deep + 1));
        }

        // Change file size degrees format
        private void LengthAuto(object sender, System.Windows.RoutedEventArgs e)
        {
            ScanerItemString.FileSizeFormat = "{0}";
            this.InvalidateVisual();
        }
        private void LengthKb(object sender, System.Windows.RoutedEventArgs e)
        {
            ScanerItemString.FileSizeFormat = "{0:kB}";
            this.InvalidateVisual();
        }
        private void LengthMb(object sender, System.Windows.RoutedEventArgs e)
        {
            ScanerItemString.FileSizeFormat = "{0:MB}";
            this.InvalidateVisual();
        }
        private void LengthGb(object sender, System.Windows.RoutedEventArgs e)
        {
            ScanerItemString.FileSizeFormat = "{0:GB}";
            this.InvalidateVisual();
        }

        // Change filse size progress formate
        private void ProgressTotal(object sender, System.Windows.RoutedEventArgs e)
        {
            this.Resources["VisibleTotal"] = Visibility.Visible;
            this.Resources["VisibleParent"] = Visibility.Collapsed;

        }
        private void ProgressParent(object sender, System.Windows.RoutedEventArgs e)
        {
            this.Resources["VisibleTotal"] = Visibility.Collapsed;
            this.Resources["VisibleParent"] = Visibility.Visible;
        }

        // Tree view handlers
        private void trFileDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
        }

        // Context menu handlers
        private void OpenInExplorer(object sender, System.Windows.RoutedEventArgs e)
        {
            SelectedItemStartProcess(trFiles.SelectedItem as TreeViewItem);
        }
        private void ExpandAllChild(object sender, System.Windows.RoutedEventArgs e)
        {
            TreeViewItem ti = trFiles.SelectedItem as TreeViewItem;
            if (ti != null)
            {
                //Expand all child   
            }
        }
        private void CollapseAllChild(object sender, System.Windows.RoutedEventArgs e)
        {
            TreeViewItem ti = trFiles.SelectedItem as TreeViewItem;
            if (ti != null)
            {
                //Collapse all child
            }
        }

        // About
        private void AboutClick(object sender, System.Windows.RoutedEventArgs e)
        {
            KDG.FoldersSize.About ab = new KDG.FoldersSize.About();
            ab.ShowDialog();
        }

        // Find methods
        private void FindItems(string mask)
        {
            if (root != null)
            {
                this.findListView.FoundItems.Clear();

                Action<ScanerItem, string> find = null;
                find = new Action<ScanerItem, string>((x, m) =>
                    {
                        if (x.Name.Contains(m))
                            this.findListView.FoundItems.Add(x);
                        if (x.Childs != null)
                            x.Childs.ForEach(c => find(c, m));
                    });
                find(root, mask);

                this.findListView.Refresh();

                System.Windows.MessageBox.Show("Search completed.");
            }
        }

        // Help methods
        static public void SelectedItemStartProcess(TreeViewItem ti)
        {
            int i = 0;
            i.With(x => ti)
                .With(x => x.DataContext)
                .With(x => x as ScanerItem)
                .Do(x => System.Diagnostics.Process.Start(x.FullName));
        }

        private void findListView_FindClick(object sender, FindEventArgs e)
        {
            FindItems(e.Mask);
        }

        private void trFileMRBUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            Point p = Mouse.GetPosition(trFiles);
            IInputElement element = trFiles.InputHitTest(p);
            this.With(x => element)
                .With(x => x as System.Windows.Controls.TreeViewItem)
                .Do(x => SelectedItemStartProcess(x));
        }

    }
}
